#include "main.h"
#include "gpio.h"
#include "led.h"
#include "usart.h"

#include "pd.h"
#include "pd_driver.h"
#include "qc.h"
#include "ufcs.h"
#include "ufcs_driver.h"

#include "key.h"

#define LONG_PRESS_TIME 500

#define SHIFT (HAL_GPIO_ReadPin(Key_SHIFT_Port, Key_SHIFT_PIN) == 0)
#define NO_SHIFT (HAL_GPIO_ReadPin(Key_SHIFT_Port, Key_SHIFT_PIN) == 1)

static volatile uint8_t g_curr_protocol = 0;
static volatile uint16_t g_curr_volt = 0;

static void set_volt(uint16_t volt) // units mv
{
	g_curr_volt = volt;
	switch(g_curr_protocol)
	{
		case 1: //pd
			PD_Set_Volt(volt);
			break;
		case 2: //ufcs
            UFCS_Set_Vol(volt);
			break;
		case 3: //qc
			QC_Set_Volt((volt+100)/1000);
			break;
	}
}

static void adjust_volt(uint8_t cmd)
{
	if(cmd & 0xF0) g_curr_volt += (cmd & 0xF) * 100;
	else g_curr_volt -= (cmd & 0xF) * 100;
	
	if((cmd & 0x0F) > 1) // qc 0.2V / step, 1V = 5 step
	{
		cmd = (cmd & 0xF0) | 0x05;
	}
	
	switch(g_curr_protocol)
	{
		case 1: //pd
			PD_Set_Volt(g_curr_volt);
			break;
		case 2: //ufcs
			break;
		case 3: //qc
			QC_Continue_Adjust(cmd);
			break;
	}
}

void shift_single_click_proc(void)
{
	set_volt(5000);
	log_printf("ufcs_single_click_proc\r\n");
}

void pd_single_click_proc(void)
{
	set_volt(9000);
	log_printf("pd_single_click_proc\r\n");
}

void pd_long_press_proc(void)
{
	PD_ShakeHand(0x32);
	g_curr_protocol = 1;
	g_curr_volt = 5000;
	log_printf("pd_long_press_proc\r\n");
}

void ufcs_single_click_proc(void)
{
	if(SHIFT) adjust_volt(0x01); // dowm 0.1 V
	else set_volt(12000);
	log_printf("ufcs_single_click_proc\r\n");
}

void ufcs_long_press_proc(void)
{
	log_printf("ufcs_long_press_proc\r\n");
	FUSB_Rd_Control(0x00);
	HAL_Delay(200);
	FUSB_Rd_Control(0x03);
    HAL_Delay(500);
	if( UFCS_Shake_Hand() != 0) // Fail
    {
        g_curr_protocol = 0;
    }
    
    HAL_Delay(20);
	
    UFCS_Get_Output_Cap(NULL);
    
    g_curr_protocol = 2;
    g_curr_volt = 5000;
}

void qc_single_click_proc(void)
{
	if(SHIFT) adjust_volt(0x11); // up 0.1V
	else set_volt(15000);
	log_printf("qc_single_click_proc\r\n");
}

void qc_long_press_proc(void)
{
	log_printf("qc_long_press_proc\r\n");
	FUSB_Rd_Control(0x00);
	HAL_Delay(200);
	FUSB_Rd_Control(0x03);
	HAL_Delay(100);
	QC_Shake_Hand();
	g_curr_protocol = 3;
}

void afc_single_click_proc(void)
{
	if(SHIFT) adjust_volt(0x0A); // down 1V
	else set_volt(20000);

	log_printf("afc_single_click_proc\r\n");
}

void afc_long_press_proc(void)
{
	log_printf("afc_long_press_proc\r\n");
}

void userA_single_click_proc(void)
{
	if(SHIFT) adjust_volt(0x1A); // up 1V
	else set_volt(20000);

	log_printf("userA_single_click_proc\r\n");
}

void userA_long_press_proc(void)
{
	log_printf("userA_long_press_proc\r\n");
}

static volatile uint32_t pd_have_fall = 0;
static volatile uint32_t pd_last_down = 0;
static volatile uint32_t pd_click_flag = 0;
void PD_Key_IRQHandler()
{
	uint32_t t = HAL_GetTick(); 
	
	if(HAL_GPIO_ReadPin(Key_PD_Port, Key_PD_PIN)) // Rise
	{
		if(pd_have_fall == 0) return; // fix chip bug
		pd_have_fall = 0;
		
		if(t - pd_last_down > LONG_PRESS_TIME) return;
		pd_click_flag = 1;
	}
	else // fall
	{
		pd_have_fall = 1;
		pd_last_down = t;
	}
}

static volatile uint32_t ufcs_have_fall = 0;
static volatile uint32_t ufcs_last_down = 0;
static volatile uint32_t ufcs_click_flag = 0;
void UFCS_Key_IRQHandler()
{
	uint32_t t = HAL_GetTick(); 
	
	if(HAL_GPIO_ReadPin(Key_UFCS_Port, Key_UFCS_PIN)) // Rise
	{
		if(ufcs_have_fall == 0) return;
		ufcs_have_fall = 0;
		if(t - ufcs_last_down > LONG_PRESS_TIME) return;
		ufcs_click_flag = 1;
	}
	else // fall
	{
		ufcs_have_fall = 1;
		ufcs_last_down = t;
	}
}

static volatile uint32_t qc_have_fall = 0;
static volatile uint32_t qc_last_down = 0;
static volatile uint32_t qc_click_flag = 0;
void QC_Key_IRQHandler()
{
	uint32_t t = HAL_GetTick(); 
	if(HAL_GPIO_ReadPin(Key_QC_Port, Key_QC_PIN)) // Rise
	{
		if(qc_have_fall == 0) return;
		qc_have_fall = 0;
		if(t - qc_last_down > LONG_PRESS_TIME) return;
		qc_click_flag = 1;
	}
	else // Fall
	{
		qc_have_fall = 1;
		qc_last_down = t;
	}
}

static volatile uint32_t afc_have_fall = 0;
static volatile uint32_t afc_last_down = 0;
static volatile uint32_t afc_click_flag = 0;
void AFC_Key_IRQHandler()
{
	uint32_t t = HAL_GetTick(); 
	
	if(HAL_GPIO_ReadPin(Key_AFC_Port, Key_AFC_PIN)) // Rise
	{
		if(afc_have_fall == 0) return;
		afc_have_fall = 0;
		if(t - afc_last_down > LONG_PRESS_TIME) return;
		afc_click_flag = 1;
	}
	else // Fall
	{
		afc_have_fall = 1;
		afc_last_down = t;
	}
}

static volatile uint32_t userA_have_fall = 0;
static volatile uint32_t userA_last_down = 0;
static volatile uint32_t userA_click_flag = 0;
void UserA_Key_IRQHandler()
{
	uint32_t t = HAL_GetTick(); 
	if(HAL_GPIO_ReadPin(Key_UserA_Port, Key_UserA_PIN)) // Rise
	{
		if(userA_have_fall == 0) return;
		userA_have_fall = 0;
		if(t - userA_last_down > LONG_PRESS_TIME) return;
		userA_click_flag = 1;
	}
	else // fall
	{
		userA_last_down = t;
		userA_have_fall = 1;
	}
}

static volatile uint32_t shift_have_fall = 0;
static volatile uint32_t shift_last_down = 0;
static volatile uint32_t shift_click_flag = 0;
void SHIFT_Key_IRQHandler()
{
	uint32_t t = HAL_GetTick(); 
	if(HAL_GPIO_ReadPin(Key_SHIFT_Port, Key_SHIFT_PIN)) // Rise
	{
		if(shift_have_fall == 0) return;
		shift_have_fall = 0;
		if(t - shift_last_down > LONG_PRESS_TIME) return;
		shift_click_flag = 1;
	}
	else // fall
	{
		shift_last_down = t;
		shift_have_fall = 1;
	}
}


void Key_Loop(void)
{
	uint32_t t = HAL_GetTick(); 
	if(pd_click_flag == 1) // pd Key click
	{
		pd_click_flag = 0;
		pd_single_click_proc();
	}
	else if ((pd_have_fall == 1) && (t - pd_last_down > LONG_PRESS_TIME)) // pd Key long press
	{
		pd_have_fall = 0;
		pd_long_press_proc();
	}
	
	if(ufcs_click_flag == 1) // ufcs Key click
	{
		ufcs_click_flag = 0;
		ufcs_single_click_proc();
	}
	else if ((ufcs_have_fall == 1) && (t - ufcs_last_down > LONG_PRESS_TIME)) // ufcs key long press
	{
		ufcs_have_fall = 0;
		ufcs_long_press_proc();
	}
	
	if(qc_click_flag == 1) // qc Key click
	{
		qc_click_flag = 0;
		qc_single_click_proc();
	}
	else if ((qc_have_fall == 1) && (t - qc_last_down > LONG_PRESS_TIME)) // qc key long press
	{
		qc_have_fall = 0;
		qc_long_press_proc();
	}
	
	if(afc_click_flag == 1) // afc Key click
	{
		afc_click_flag = 0;
		afc_single_click_proc();
	}
	else if ((afc_have_fall == 1) && (t - afc_last_down > LONG_PRESS_TIME)) // afc key long press
	{
		afc_have_fall = 0;
		afc_long_press_proc();
	}
	
	if(userA_click_flag == 1) // afc Key click
	{
		userA_click_flag = 0;
		userA_single_click_proc();
	}
	else if ((userA_have_fall == 1) && (t - userA_last_down > LONG_PRESS_TIME)) // afc key long press
	{
		userA_have_fall = 0;
		userA_long_press_proc();
	}
	
	if(shift_click_flag == 1) // shift Key click
	{
		shift_click_flag = 0;
		shift_single_click_proc();
	}
	else if ((shift_have_fall == 1) && (t - shift_last_down > LONG_PRESS_TIME)) // afc key long press
	{
		shift_have_fall = 0;
	}
}
